//
//  QDNetworkingManager.swift
//  QDMetroClient
//
//  Created by YueWen on 2019/3/4.
//  Copyright © 2019 YueWen. All rights reserved.
//

import UIKit
import HandyJSON

/// 网络请求成功
typealias QDNetworkingSuccess = (String,[String: Any])->()
typealias QDNetworkingArraySuccess = (String,[[String: Any]])->()
/// 网络异常状态
typealias QDNetworkingError = (String,RequestErrorType)->()

/// Swift的网络请求
final class QDNetworkingManager: NWNetWorkingManager {

    /// Swift 统一进行网络请求的方法
    static func request(needLogin: Bool = true,
                        url: String,
                        method: HTTPMethod = .POST ,
                        isArray: Bool = false,
                        paramteres:[String: Any]? = [:],
                        success:QDNetworkingSuccess? = nil,
                        arraySuccess: QDNetworkingArraySuccess? = nil,
                        errorHandler: QDNetworkingError? = nil){
        
        /// 开始请求
        request(withUrlString: url, method: method, parameters: paramteres, success:
            { (task, data) in
                
                /// 类型以及错误类型
                guard let respcod = data["respcod"] as? String, let type = RequestErrorType.init(rawValue: respcod)  else {
                    errorHandler?(data["respmsg"] as? String ?? "", .unknowned); return
                }
                
                // 如果成功
                if type == .success, let info = data["data"] as? [String : Any], !isArray {
                    success?(data["respmsg"] as? String ?? "",info); return
                }
                
                else if type == .success, let info = data["data"] as? [[String : Any]], isArray {
                    arraySuccess?(data["respmsg"] as? String ?? "",info); return
                }
                
                // 登陆失效，取消本地
                if type == .unLogin {//如果是登陆失效
                    // 取消本地登陆状态
                    QDUserStatus.isLogin = false
                    // 发送通知
//                    NotificationCenter.default.post(name: QDLogoutCompleteNotificationName, object: nil)
                    
                    // 需要登录
                    if needLogin {
                        // 返回
                        errorHandler?(data["respmsg"] as? String ?? "", type); return
                    }
                }
                // 返回失败情况
                errorHandler?(data["respmsg"] as? String ?? "", type)
                
        }) { (task, error) in
            //返回错误
            errorHandler?(error.localizedDescription, .error)
        }
    }
}




//MARK: 站点
extension QDNetworkingManager {
    
    /// 接收容器
    private struct QDAllStationsContainer: HandyJSON {
        /// 最近站点
        var nearStation = QDNearMetroStationContainer()
        /// 线路下的所有站点
        var stationData = [QDMetroLine]()
    }
    
    /// 请求所有的站点
    static func requestAllStations(latitude: Float = QDLocationManager.latitude().floatValue,
                                   longitude: Float = QDLocationManager.longitude().floatValue,
                                   complete:@escaping (QDNearMetroStationContainer,[QDMetroLine])->(),
                                   fail: @escaping QDNetworkingError){
        
        request(url: allStationsUrl, paramteres: ["x": latitude, "y": longitude], success: { (msg, data) in
            
            guard let container = QDAllStationsContainer.deserialize(from: data) else {
                fail("数据解析错误!",.unNormal); return
            }
    
            complete(container.nearStation,container.stationData)
            
        }) { (msg, errorType) in
            fail(msg,errorType)
        }
    }
}


extension Array where Element ==  QDMetroLine {
    
    
    /// 获得所有的站点，排除重复
    func metroStationsWithoutRepeat() -> [QDMetroStation] {
        
        // 如果为空，返回空数组
        if isEmpty { return [QDMetroStation]() }
        
        let stations = flatMap { $0.stationData }
        var stationIdsSet = Set<String>()
        var allStations = [QDMetroStation]()
        
        for station in stations {
            if !stationIdsSet.contains(station.id){
                allStations.append(station)
                stationIdsSet.insert(station.id)
            }
        }
        
        return allStations
    }
}








//MARK: 支付渠道
extension QDNetworkingManager {
    
    /// 支付渠道的容器
    struct QDPayTypeContainer: HandyJSON {
        
        /// 是否存在黑名单
        var inBlack = false
        /// 默认支付类型
        var defaultAgreement = ""
        /// 卡片类型 02-扫码 03-NFC 04-公交
        var cardType = ""
        /// 支付渠道
        var channelList = [QDPayTypeModel]()
        /// 信用能力
        var contractAccept = true
        /// 是否存在默认支付方式
        var hasDefaultAgreement = true
        /// 逻辑卡号
        var cardNo = ""
    }
    
    
    /// 请求支付渠道
    static func requestPayTypeList(complete: @escaping ([QDPayTypeModel],Bool,String)->(),fail: QDNetworkingError?) {
        
        request(url: payListUrl, success: { (msg, data) in
            
            guard let payContainer =  QDPayTypeContainer.deserialize(from: data) else {
                fail?("数据类型错误",.unNormal); return
            }
            
            complete(payContainer.channelList,payContainer.inBlack,payContainer.cardNo)
            
        }) { (msg, errorType) in
            fail?(msg,errorType)
        }
    }
}


private extension QDPaySignType {
    
    /// 基础的参数
    func baseSignParameter() -> [String: String]{
        return ["realName":"","phoneNum":"","cardNum":"","idCode":"","wechatAuthToken":""]
    }
}

//MARK: 签约
extension QDNetworkingManager {
    
    /// 请求签约渠道
    static func requestPaySign(type: QDPaySignType,data: [String: String],complete:@escaping ((String,String)->()),fail:@escaping QDNetworkingError){
        
        //认证的参数合并
        let signParamters = type.baseSignParameter().merging(data) { $1 }
        
        //首选进行认证
        requestSignCertification(data: signParamters, complete: { (id) in
        
            //根据id进行签约
            request(url: signInfoUrl, paramteres: ["id":id,"payChannelCode":type.rawValue], success: { (msg, data) in
                
                /// 获得数据并且转换
                guard let signInfo = data["signInfo"] else {
                    fail("signInfo 数据不存在",.unNormal); return
                }
                
                guard let signString = signInfo as? String else {
                     fail("signInfo 数据类型不正确",.unNormal); return
                }
                
                print("\(signString)")
                if type == .Weixin {//进行微信解析
                    complete(QDPaymentUntility.wxpaySigning(signString),id)
                    
                }else if type == .ALiPay || type == .Union {//是支付宝或者银联
                    complete(signString,id)
                    
                }else {
                    fail("不支持的签约类型",.unknowned)
                }
                
            }, errorHandler: { (msg, errorType) in
                
                fail(msg,errorType)//请求签约数据失败
            })
            
        }) { (msg, errorType) in
            fail(msg,errorType)//请求验证失败
        }
        
    }
    
    /// 请求认证信息
    private static func requestSignCertification(data:[String: String],complete:@escaping ((String)->()),fail:@escaping QDNetworkingError){
        
        request(url: signCertificationUrl, paramteres: data, success: { (msg, data) in
            
            let id = data["id"] as? Int ?? -1 //获得返回的Id
            
            // id不能为空
            if id == -1 { fail("id类型错误",.unNormal); return }
            complete("\(id)") //返回id
            
        }) { (msg, erroType) in
            fail(msg,erroType)
        }
    }
}




//MARK: 便捷服务列表
extension QDNetworkingManager {
    
    enum ConvenienceType: String {
        /// 基础设施
        case base = "40"
        /// 障碍相关设施
        case barrier = "34"
        /// 生活便利服务
        case life = "41"
    }
    
    /// 请求便捷服务
    static func requestConvenienceMessage(type: QDNetworkingManager.ConvenienceType, page: Int = 0, complete: @escaping (([QDTextListModel]) -> ()), fail: QDNetworkingError? = nil){
        
        request(url: QDStaticHostUrl + "/document/convenience", isArray: true, paramteres: ["size":"10","page": page, "type": type.rawValue], arraySuccess: { (msg, datas) in
            
            //进行转型
            guard let listModels = NSArray.yy_modelArray(with: QDTextListModel.self, json: datas) else {
                fail?("数据格式错误",.unknowned); return
            }
            
            complete(listModels as? [QDTextListModel] ?? [QDTextListModel]())
            
        }) { (msg, errorType) in
            fail?(msg,errorType)
        }
        
    }
}



//MARK: 请求静态资源
extension QDNetworkingManager {
    
    enum StaticType: String {
        /// 通讯地址
        case address
        /// 客服电话
        case serviceTel = "ServiceTel"
        /// 微信客服号码
        case weixinService = "weixinService"
    }
    
    /// 请求静态资源
    static func requestStaticData(success:@escaping (([String : Any])->()),
                                  fail: QDNetworkingError? = nil){
        
        request(url: QDStaticHostUrl + "/static/list", success: { (msg, data) in
        
            success(data)
            
        }) { (msg, errorType) in
            
            fail?(msg,errorType)
        }
    }
}


//MARK: 广告位

/// 请求广告位
extension QDNetworkingManager {
    
    /// 广告类型
    enum AdType: String {
        /// 乘车码
        case metroBus = "1"
        /// 支付管理
        case pay = "2"
    }
    
    
    /// 请求广告位
    static func requestStaticAds(type :AdType = .metroBus ,success:@escaping (([QDAdvertisementModel])->()),error: QDNetworkingError?) {
        
        QDNetworkingManager.request(url: pageAdsUrl, isArray: true, paramteres: ["type":type.rawValue], arraySuccess: { (msg, data) in
            
            guard let datas = [QDAdvertisementModel].deserialize(from: data) as? [QDAdvertisementModel] else {
                error?("数据结构错误",.unNormal); return
            }
            
            success(datas)
            
        }, errorHandler: error)
    }
}




//MARK: 文章收藏点赞
extension QDNetworkingManager {
    
    /// 文章响应类型
    enum ArticleActionType: String {
        /// 收藏操作
        case collect = "1"
        /// 点赞操作
        case favorite = "2"
    }
    
    
    /// 文章的点赞收藏操作
    static func articleDidAction(articleId: String,
                                 type: ArticleActionType = .collect,
                                 complete:@escaping (([String: Any],String)->()),
                                 fail:QDNetworkingError?) {
        

        request(url: QDCustomerHostUrl + "/user/favorite", paramteres: ["articleId":articleId,"type": type.rawValue], success: { (msg, data) in
            
            complete(data,msg);
            
        }) { (msg, errorType) in
            
            fail?(msg, errorType);
        }
    }
    
}
